package c2.cross.business.rank.manager;

import c2.cross.business.rank.CrossRankModule;
import c2.cross.business.rank.data.CrossRankKv;
import c2.cross.business.rank.h.BaseSingleValueRankHandler;
import c2.cross.business.rank.h.CrossRankActivityHandlerImpl;
import c2.cross.business.rank.h.ICrossRankHandler;
import cate.common.table.activity.crossrankactivity.row.CrossRankActivityBaseRow;
import cate.common.table.d.GDFunc;
import cate.common.util.TimeTool;
import cate.game.activity.config.ActivityBaseCfg;
import cate.game.rank.po.Rank;
import easy.java.dev.note.NoteField;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;

import java.util.*;

/**
 * 跨服活动排行榜管理
 */
@Slf4j
public class CrossRankActivityManager extends BaseCrossRankFuncManager {
    @NoteField("跨服排行活动处理器集合")
    private final Map<Integer, CrossRankActivityHandlerImpl> handlers = new HashMap<>();

    @NoteField(value = "所有跨服排行活动配置",detail = "跨服排行只读自然日活动")
    private final List<ActivityBaseCfg> allConfigs = new ArrayList<>();

    @NoteField("下次检测时间")
    protected long checkTime;

    @Override
    public void initSelf(CrossRankModule parent) {
        allConfigs.clear();

        parent.getActTable().natural.getList().forEach(row -> {
            if (GDFunc.CrossRankFunc.of(row.funcId) != null) {
                ActivityBaseCfg cfg = new ActivityBaseCfg();
                cfg.init(row);
                cfg.startTime = TimeTool.parseTime(row.startTimeStr);
                cfg.endTime = TimeTool.parseTime(row.endTimeStr);
                if (cfg.endTime < System.currentTimeMillis()) {
                    return;
                }
                allConfigs.add(cfg);
            }
        });

        // 活动功能都开启一个记录榜
        parent.getRankActTable().base.getList().forEach(row -> {
            if (!handlers.containsKey(row.rankId)) {
                CrossRankActivityHandlerImpl handler = new CrossRankActivityHandlerImpl(row, parent.getDb());
                handlers.put(row.rankId, handler);
            }
        });
        // 记录活动开启中的状态
        status().getOpenActivities().forEach(cfg -> {
            CrossRankActivityBaseRow row = parent.getRankActTable().base.get(cfg.configTid);
            if (row != null) {
                Optional.ofNullable(handlers.get(row.rankId)).ifPresent(handler -> handler.setConfigTid(cfg.configTid));
            }
        });
        // 刷新检测时间
        updateActivities();
        resetCheckTime();
    }

    /**
     * 存储记录
     */
    private CrossRankKv status() {
        return parent.getKv();
    }

    @Override
    public void tick() {
        handlers.values().forEach(BaseSingleValueRankHandler::tick);
        if (checkTime == 0 || checkTime > System.currentTimeMillis()) {
            return;
        }
        updateActivities();
        resetCheckTime();
    }

    @Override
    public boolean focusRankId(int rankId) {
        return handlers.containsKey(rankId) && handlers.get(rankId).active();
    }

    @Override
    public Optional<ICrossRankHandler> tryGetCrossSingleRankHandler(int rankId) {
        return Optional.ofNullable(handlers.get(rankId));
    }

    @Override
    public void noticeMergeChangeCross(int srvId) {
        super.noticeMergeChangeCross(srvId);
        handlers.values().forEach(handler -> handler.removeBySrvId(srvId));
    }

    @Override
    public void noticeMergeIntoCross(int oldId, int curId) {
        super.noticeMergeIntoCross(oldId, curId);
        handlers.values().forEach(handler -> handler.changeSrvId(oldId, curId));
    }

    /**
     * 根据活动配置获取排行实现
     */
    private CrossRankActivityHandlerImpl getHandlerByCfg(ActivityBaseCfg cfg) {
        CrossRankActivityBaseRow row = parent.getRankActTable().base.get(cfg.configTid);
        if (row != null) {
            return handlers.get(row.rankId);
        }
        return null;
    }

    private CrossRankActivityBaseRow getBaseConfig(int configTid) {
        return parent.getRankActTable().base.get(configTid);
    }

    /**
     * 活动更新
     */
    protected void updateActivities() {
        // 之前记录的开启的活动
        List<ActivityBaseCfg> records = status().getOpenActivities();
        // 当前需要开启的活动
        List<ActivityBaseCfg> curs = calCurOpenActivity();
        // 当前需要结束的活动
        records.forEach(cfg ->  {
            if (!curs.contains(cfg)) {
                recordClose(cfg);
                onClose(cfg);
            }
        });
        // 检测后发现需要新增或变更的活动
        curs.forEach(cfg -> {
            if (!records.contains(cfg)) {
                recordOpen(cfg);
                onOpen(cfg);
            }
        });
        status().setOpenActivities(curs);
    }

    /**
     * 获取所有当前开启的活动
     */
    private List<ActivityBaseCfg> calCurOpenActivity() {
        List<ActivityBaseCfg> ingActivity = new ArrayList<>();
        // 同一个功能id只能有一个活动开启
        Set<Integer> funcIdSet = new HashSet<>();
        long time = System.currentTimeMillis();
        for (ActivityBaseCfg cfg : allConfigs) {
            if (time >= cfg.startTime && time < cfg.endTime) {
                if (funcIdSet.contains(cfg.funcId)) {
                    log.error("[CrossRankActivityManager] 功能id={}的活动时间配置重复,类型={}活动ID={}", cfg.funcId, cfg.type, cfg.activityId);
                    continue;
                }
                funcIdSet.add(cfg.funcId);
                ingActivity.add(cfg);
            }
        }
        return ingActivity;
    }

    /**
     * 活动开启
     */
    public void onOpen(ActivityBaseCfg cfg) {
        CrossRankActivityHandlerImpl handler = getHandlerByCfg(cfg);
        if (handler == null) {
            return;
        }
        // 开启时清理老数据
        handler.clear();
        // 设置为新的配置ID
        handler.setConfigTid(cfg.configTid);
    }

    /**
     * 活动关闭
     */
    public void onClose(ActivityBaseCfg cfg) {
        CrossRankActivityHandlerImpl handler = getHandlerByCfg(cfg);
        if (handler == null) {
            return;
        }
        if (handler.active()) {
            handleCloseReward(handler);
            handler.setConfigTid(0);
        }
    }

    /**
     * 处理结算邮件
     *
     * @param handler 排行处理
     */
    private void handleCloseReward(CrossRankActivityHandlerImpl handler) {
        CrossRankActivityBaseRow config = getBaseConfig(handler.getConfigTid());
        if (config.mailId == 0) {
            // 没配邮件就不发了，嘿嘿嘿
            return;
        }
        Map<Integer, Map<Integer, Rank>> srvIdToRankList = new HashMap<>();
        List<Rank> list = handler.getRankList(0);
        for (int i = 0; i < list.size(); i++) {
            Rank rank = list.get(i);
            if (rank.owner == null || rank.owner.base == null) {
                continue;
            }
            int index = i + 1;
            printRank(handler.getTag(), index, rank);
            Map<Integer, Rank> srvMap = srvIdToRankList.computeIfAbsent(rank.owner.base.srvId,
                    k -> new HashMap<>());
            srvMap.put(index, rank);
        }
        srvIdToRankList.forEach((srvId, rankMap) -> {
            Map<Integer, Rank> failMap = parent.msg.sendGameCrossRankActivitySettle(srvId, handler.getConfigTid(), rankMap);
            if (MapUtils.isNotEmpty(failMap)) {
                rankMap.forEach((index, rank) -> printFailRank(handler.getTag(), index, rank));
            }
        });
    }

    /**
     * 打印排行榜信息
     *
     * @param tag 排行榜TAG
     * @param rank 数据
     */
    private void printRank(String tag, int index, Rank rank) {
        log.info("跨服排行榜活动TAG=[{}]发送邮件 --- 第{}名 name:{}, uid:{}, value:{}",
                tag, index, rank.owner.base.name, rank.owner.uid, rank.value);
    }

    /**
     * 打印发放奖励失败信息
     *
     * @param tag 排行榜TAG
     * @param rank 数据
     */
    private void printFailRank(String tag, int index, Rank rank) {
        log.info("[CTRL] 跨服排行榜活动TAG=[{}]发送失败!!! --- 第{}名 name:{}, uid:{}, value:{}",
                tag, index, rank.owner.base.name, rank.owner.uid, rank.value);
    }

    /**
     * 重置下次活动变更时间
     */
    private void resetCheckTime() {
        checkTime = 0;
        long temp = 0L;
        long now = System.currentTimeMillis();
        for (ActivityBaseCfg cfg : allConfigs) {
            if (cfg.startTime > now) {
                if (temp == 0 || temp > cfg.startTime) {
                    temp = cfg.startTime;
                }
            } else {
                if (cfg.endTime > now) {
                    if (temp == 0 || temp > cfg.endTime) {
                        temp = cfg.endTime;
                    }
                }
            }
        }
        checkTime = temp;
        if (checkTime > 0) {
            log.info("[CrossRankActivityManager] 下次活动变更时间为:{}", TimeTool.getDF2().format(new Date(checkTime)));
        } else {
            log.info("[CrossRankActivityManager] 在未来已经没有活动了");
        }
    }

    /**
     * 记录活动开启
     */
    private void recordOpen(ActivityBaseCfg cfg) {
        log.info("[CrossRankActivityManager] 活动开启 功能id:{} 活动id:{}", cfg.funcId, cfg.activityId);
    }

    /**
     * 记录活动结束
     */
    private void recordClose(ActivityBaseCfg cfg) {
        log.info("[CrossRankActivityManager] 活动结束 功能id:{} 活动id:{}", cfg.funcId, cfg.activityId);
    }

    public void save() {
        handlers.values().forEach(BaseSingleValueRankHandler::save);
    }
}
